// https://leetcode.cn/problems/print-zero-even-odd/
// Created by ade on 2022/11/2.
//
#include <semaphore.h>
class ZeroEvenOdd {
private:
    int n;
    sem_t s0, s1, s2;

public:
    ZeroEvenOdd(int n) {
        this->n = n;
        sem_init(&s0, 0, 1);
        sem_init(&s1, 0, 0);
        sem_init(&s2, 0, 0);
    }

    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber) {
        for (int i = 1; i <= n; i++) {
            sem_wait(&s0);
            printNumber(0);
            if (i % 2 == 1) {
                sem_post(&s1);
            } else {
                sem_post(&s2);
            }
        }
    }

    void odd(function<void(int)> printNumber) {
        for (int i = 1; i <= n; i = i + 2) {
            sem_wait(&s1);
            printNumber(i);
            sem_post(&s0);
        }
    }

    void even(function<void(int)> printNumber) {
        for (int i = 2; i <= n; i = i + 2) {
            sem_wait(&s2);
            printNumber(i);
            sem_post(&s0);
        }
    }
};